package com.miplus.ccrm.core.service.strategy;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.github.yulichang.wrapper.DeleteJoinWrapper;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.miplus.ccrm.common.CmdResVo;
import com.miplus.ccrm.common.ServiceException;
import com.miplus.ccrm.core.controller.vo.strategy.*;
import com.miplus.ccrm.core.mapper.CfgRuleTaskStepLinkMapper;
import com.miplus.ccrm.core.pojo.*;
import com.miplus.ccrm.core.service.strategy.CfgRuleTaskService;
import com.miplus.ccrm.core.mapper.CfgRuleTaskMapper;
import com.miplus.ccrm.core.service.utils.ExecutorServiceImpl;
import com.miplus.ccrm.core.service.utils.LogXxlJobService;
import com.miplus.ccrm.core.utils.EnumRuleStepAction;
import com.miplus.ccrm.core.utils.EnumRuleTaskRunStatus;
import com.miplus.ccrm.core.utils.EnumXxlLogOpType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import sun.util.resources.cldr.CalendarData;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;

/**
* @author wangzl
* @description 针对表【cfg_rule_task】的数据库操作Service实现
* @createDate 2024-10-22 10:33:33
*/
@Slf4j
@Service
public class CfgRuleTaskServiceImpl extends MPJBaseServiceImpl<CfgRuleTaskMapper, CfgRuleTask>
    implements CfgRuleTaskService
{
    @Resource
    CfgRuleTaskStepLinkMapper cfgRuleTaskStepLinkMapper;

    @Resource
    CfgRuleTaskStepsService cfgRuleTaskStepsService;

    @Resource
    LogXxlJobService logXxlJobService;

    @Resource
    ExecutorServiceImpl executorService;


    @Override
    public IPage<RuleTaskListResVo> getRuleTaskList(String usrId, RuleTaskReqVo ruleTaskReqVo)
    {
        return selectJoinListPage(new Page<>(ruleTaskReqVo.getPageNum(), ruleTaskReqVo.getPageSize()),
                RuleTaskListResVo.class,
                new MPJLambdaWrapper<CfgRuleTask>()
                        .leftJoin("sys_grp g on g.grpid=t.dept_id")
                        .selectAll(CfgRuleTask.class)
                        .selectAs("g.grpname",RuleTaskListResVo::getDeptName)
                        .selectAs("fun_getnames('RULE.TASK.INTERVALTYPE',t.interval_type)",RuleTaskListResVo::getIntervalTypeDesc)
                        .selectAs("fun_getnames('RULE.TASK.TYPE',t.rule_task_type)",RuleTaskListResVo::getRuleTaskTypeDesc)
                        .eq(StringUtils.isNotBlank(ruleTaskReqVo.getDeptId()),CfgRuleTask::getDeptId,ruleTaskReqVo.getDeptId())
                        .like(StringUtils.isNotBlank(ruleTaskReqVo.getTaskName()),CfgRuleTask::getRuleTaskName,ruleTaskReqVo.getTaskName())
                        .eq(ObjectUtils.isNotNull(ruleTaskReqVo.getStatus()),CfgRuleTask::getStatus,ruleTaskReqVo.getStatus())
                        .eq(ObjectUtils.isNotNull(ruleTaskReqVo.getTaskType()),CfgRuleTask::getRuleTaskType,ruleTaskReqVo.getTaskType())
                        .ge(StringUtils.isNotBlank(ruleTaskReqVo.getStartDate()),CfgRuleTask::getStartDate,ruleTaskReqVo.getStartDate())
                        .le(StringUtils.isNotBlank(ruleTaskReqVo.getEndDate()),CfgRuleTask::getStartDate,ruleTaskReqVo.getEndDate())
        ).convert(x->{
            x.setExecuteStatusDesc(EnumRuleTaskRunStatus.getDescByCode(x.getExecuteStatus()));
            return x;
        });

    }
    @Override
    public RuleTaskListResVo getRuleTaskInfo(Long taskId)
    {
        return selectJoinOne(RuleTaskListResVo.class,
                new MPJLambdaWrapper<CfgRuleTask>()
                        .selectAs("g.grpname",RuleTaskListResVo::getDeptName)
                        .selectAs("fun_getnames('RULE.TASK.INTERVALTYPE',t.interval_type)",RuleTaskListResVo::getIntervalTypeDesc)
                        .leftJoin("sys_grp g on g.grpid=t.dept_id")
                        .selectAll(CfgRuleTask.class)
                        .selectAs("fun_getnames('RULE.TASK.TYPE',t.rule_task_type)",RuleTaskListResVo::getRuleTaskTypeDesc)
                        .eq(CfgRuleTask::getRuleTaskId,taskId)
        );
    }
    @Override
    public  CmdResVo addRuleTask(String usrId, CfgRuleTask cfgRuleTask)
    {
        cfgRuleTask.setCrdt(new Date());
        cfgRuleTask.setCrusr(usrId);
        save(cfgRuleTask);
        return new CmdResVo(1,cfgRuleTask.getRuleTaskId().toString());
    }
    @Override
    public  CmdResVo updateRuleTask(String usrId, CfgRuleTask cfgRuleTask)
    {
        if(ObjectUtils.isNull(cfgRuleTask.getRuleTaskId()))
        {
            throw  new ServiceException(1001,"决策ID不能为空");
        }
        CfgRuleTask cfgRuleTask1 = getById(cfgRuleTask.getRuleTaskId());
        if( cfgRuleTask1 == null){
            throw  new ServiceException(1001,"该决策任务不存在");
        }
        cfgRuleTask.setMddt(new Date());
        cfgRuleTask.setMdusr(usrId);
        updateById(cfgRuleTask);
        return new CmdResVo(1);
    }

    @Override
    public CmdResVo deleteRuleTask( Long taskId)
    {
        if(ObjectUtils.isNull(taskId))
        {
            throw  new ServiceException(1001,"决策ID不能为空");
        }
        CfgRuleTask cfgRuleTask1 = getById(taskId);
        if( cfgRuleTask1 == null){
            throw  new ServiceException(1001,"该决策任务不存在");
        }
        removeById(taskId);
        return new CmdResVo(1);
    }

    @Override
    public IPage<RuleStepListResVo> getRuleTaskStepList(Integer pageNum, Integer pageSize, Long ruleTaskId)
    {

        return selectJoinListPage(
                new Page<>(pageNum,pageSize),
                RuleStepListResVo.class,
                new MPJLambdaWrapper<CfgRuleTask>()
                        .innerJoin(CfgRuleTaskStepLink.class,CfgRuleTaskStepLink::getRuleTaskId,CfgRuleTask::getRuleTaskId)
                        .innerJoin(CfgRuleTaskSteps.class, "crt",CfgRuleTaskSteps::getRuleStepId,CfgRuleTaskStepLink::getRuleStepId)
                        .leftJoin("cp_calllist cc on cc.clid = crt.clid")
                        .selectAs("fun_getnames('RULE.STEP.ACTIONCODE',crt.action_code)",RuleStepListResVo::getActionCodeDesc)
                        .selectAll(CfgRuleTaskSteps.class)
                        .selectAs(CfgRuleTaskStepLink::getSeqnum,RuleStepListResVo::getSeqnum)
                        .selectAs("cc.name",RuleStepListResVo::getClName)
                        .eq(CfgRuleTask::getRuleTaskId,ruleTaskId)
                        .orderByAsc(CfgRuleTaskStepLink::getSeqnum)
        );

    }

    @Override
    public CmdResVo removeTaskStep(String usrId, Long ruleTaskId, Long ruleStepId) {
        CfgRuleTask cfgRuleTask = getById(ruleTaskId);
        if( cfgRuleTask == null){
            throw  new ServiceException(1001,"该决策任务不存在");
        }
        CfgRuleTaskStepLink cfgRuleTaskStepLink = cfgRuleTaskStepLinkMapper.selectOne(new LambdaQueryWrapper<CfgRuleTaskStepLink>()
                .eq(CfgRuleTaskStepLink::getRuleTaskId,ruleTaskId)
                .eq(CfgRuleTaskStepLink::getRuleStepId,ruleStepId)
        );
        if( cfgRuleTaskStepLink == null)
        {
            throw  new ServiceException(1001,"当前策略不存在");
        }

        cfgRuleTaskStepLinkMapper.deleteRuleTaskStepLink(ruleTaskId,ruleStepId,cfgRuleTaskStepLink.getSeqnum());
        cfgRuleTask.setMdusr(usrId);
        cfgRuleTask.setMddt(new Date());
        updateById(cfgRuleTask);
        return new CmdResVo(1);
    }

    @Override
    public CmdResVo addTaskStep(String usrId, RuleTaskStepLinkReqVo vo ) {
        CfgRuleTask cfgRuleTask = getById(vo.getRuleTaskId());
        if( cfgRuleTask == null){
            throw  new ServiceException(1001,"该决策任务不存在");
        }
        String[] s = vo.getRuleStepIdList().split(",");
        for( String stepId : s) {
            Long ruleStepId = Long.parseLong(stepId);
            addTaskStepLink(usrId, cfgRuleTask, ruleStepId);
        }
        cfgRuleTask.setMdusr(usrId);
        cfgRuleTask.setMddt(new Date());
        updateById(cfgRuleTask);
        return new CmdResVo(1);
    }
    private  CmdResVo addTaskStepLink(String usrId, CfgRuleTask cfgRuleTask, Long ruleStepId) {

        if( cfgRuleTask == null){
            throw  new ServiceException(1001,"该决策任务不存在");
        }
        cfgRuleTaskStepLinkMapper.addRuleTaskStepLink(usrId, cfgRuleTask.getRuleTaskId(),ruleStepId);
        cfgRuleTask.setMdusr(usrId);
        cfgRuleTask.setMddt(new Date());
        updateById(cfgRuleTask);
        return new CmdResVo(1);

    }
    @Override
    public CmdResVo changeTaskStepSeq(String usrId, Long ruleTaskId, Long ruleStepId, String upOrDown)
    {
        CfgRuleTask cfgRuleTask = getById(ruleTaskId);
        if( cfgRuleTask == null){
            throw  new ServiceException(1001,"该决策任务不存在");
        }
        CfgRuleTaskStepLink cfgRuleTaskStepLink = cfgRuleTaskStepLinkMapper.selectOne(new LambdaQueryWrapper<CfgRuleTaskStepLink>()
                        .eq(CfgRuleTaskStepLink::getRuleTaskId,ruleTaskId)
                .eq(CfgRuleTaskStepLink::getRuleStepId,ruleStepId)
        );
        if( cfgRuleTaskStepLink == null){
            throw  new ServiceException(1001,"找不到对应的策略");
        }
        log.trace("-----------" + upOrDown + "-------" + cfgRuleTaskStepLink.getSeqnum());
        if(upOrDown.equalsIgnoreCase("up") && cfgRuleTaskStepLink.getSeqnum() != 1)
        {
            log.trace("----------OK-");
            cfgRuleTaskStepLinkMapper.upRuleTaskStep(ruleTaskId,ruleStepId,cfgRuleTaskStepLink.getSeqnum());
        }
        else if( upOrDown.equalsIgnoreCase("down")) {
            long count =  cfgRuleTaskStepLinkMapper.selectCount(
                    new LambdaQueryWrapper<CfgRuleTaskStepLink>()
                            .eq(CfgRuleTaskStepLink::getRuleTaskId,ruleTaskId)
            );
            if( cfgRuleTaskStepLink.getSeqnum() == count){
                return new CmdResVo(1);
            }
            cfgRuleTaskStepLinkMapper.downRuleTaskStep(ruleTaskId, ruleStepId,cfgRuleTaskStepLink.getSeqnum());
        }
        cfgRuleTask.setMdusr(usrId);
        cfgRuleTask.setMddt(new Date());
        updateById(cfgRuleTask);
        return new CmdResVo(1);
    }
    @Override
    public CmdResVo runTask(String usrId, Long ruleTaskId, Integer isManual)
    {
        LogXxlJob logXxlJob = new LogXxlJob();
        logXxlJob.setRuleTaskId(ruleTaskId);
        CfgRuleTask cfgRuleTask = getById(ruleTaskId);
        if( cfgRuleTask == null){
            //throw  new ServiceException(1001,"该决策任务不存在");
            logXxlJobService.log(logXxlJob, EnumXxlLogOpType.TaskStart.value,0,0,2,null,"该决策任务不存在");
            return new CmdResVo(0,"该决策任务不存在");
        }
        if( !cfgRuleTask.getStatus().equals("1"))
        {
            logXxlJobService.log(logXxlJob, EnumXxlLogOpType.TaskStart.value,0,0,2,null,"该决策任务状态无效");
            return new CmdResVo(0,"该决策任务状态无效");
        }
        Calendar calendar = Calendar.getInstance();
        Date now = calendar.getTime();

        calendar.add(Calendar.DATE,-1);
        Date yesterday = calendar.getTime();

        log.info("rule task: id:{},now:<{}>,startdate:<{}>, enddate:<{}>",cfgRuleTask.getRuleTaskId(),now, cfgRuleTask.getStartDate(),cfgRuleTask.getEndDate());
        if( ObjectUtils.isNotNull(cfgRuleTask.getStartDate()) && cfgRuleTask.getStartDate().after(now))
        {
            logXxlJobService.log(logXxlJob, EnumXxlLogOpType.TaskStart.value,0,0,2,null,"没有到执行开始时间");
            return new CmdResVo(0,"没有到执行开始时间范围");
            //throw  new ServiceException(1001,"没有到执行开始时间");
        }
        if( ObjectUtils.isNotNull(cfgRuleTask.getEndDate()) && cfgRuleTask.getEndDate().before(yesterday))
        {
            //throw  new ServiceException(1001,"已经超过执行时间");
            logXxlJobService.log(logXxlJob, EnumXxlLogOpType.TaskStart.value,0,0,2,null,"已经超过执行时间");
            return new CmdResVo(0,"已经超过执行时间范围");

        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm");
        String currTime = simpleDateFormat.format(new Date());

        if(ObjectUtils.isNotEmpty(cfgRuleTask.getStartExecuteTime())
                && cfgRuleTask.getStartExecuteTime().compareTo(currTime) >0 )
        {
            //throw  new ServiceException(1001,"执行未开始");
            logXxlJobService.log(logXxlJob, EnumXxlLogOpType.TaskStart.value, 0,0,2,null,"执行未开始");
            return new CmdResVo(0,"执行未开始");
        }
        if(ObjectUtils.isNotEmpty(cfgRuleTask.getEndExecuteTime())
                && cfgRuleTask.getEndExecuteTime().compareTo(currTime) < 0 )
        {
            //throw  new ServiceException(1001,"当前已超过执行截至时间");
            logXxlJobService.log(logXxlJob, EnumXxlLogOpType.TaskStart.value, 0,0,2,null,"当前已超过执行截至时间");
            return new CmdResVo(0,"当前已超过执行截至时间");
        }
        boolean caseSyncOK = true;
        if(ObjectUtils.isNotNull(cfgRuleTask.getCheckCaseSyncFinish()) && cfgRuleTask.getCheckCaseSyncFinish() == 1)
        {
            //检查案件是否同步完成。
            caseSyncOK = true;
        }
        if(!caseSyncOK) {
            //throw new ServiceException(1001, "案件没有同步完成");
            logXxlJobService.log(logXxlJob, EnumXxlLogOpType.TaskStart.value,0,0,2,null,"案件没有同步完成");
            return new CmdResVo(0,"案件没有同步完成");
        }
        logXxlJobService.log(logXxlJob, EnumXxlLogOpType.TaskStart.value,0,0,0,null,"开始执行任务");
        update( new LambdaUpdateWrapper<CfgRuleTask>()
                .set(CfgRuleTask::getRunStartTime,new Date())
                .set(CfgRuleTask::getExecuteStatus, EnumRuleTaskRunStatus.running.value)
                .eq(CfgRuleTask::getRuleTaskId,cfgRuleTask.getRuleTaskId())
        );
        List<CfgRuleTaskSteps> cfgRuleTaskStepsList = selectJoinList(
                CfgRuleTaskSteps.class,
                new MPJLambdaWrapper<CfgRuleTask>()
                        .leftJoin(CfgRuleTaskStepLink.class,CfgRuleTaskStepLink::getRuleTaskId,CfgRuleTask::getRuleTaskId)
                        .leftJoin(CfgRuleTaskSteps.class, "crt",CfgRuleTaskSteps::getRuleStepId,CfgRuleTaskStepLink::getRuleStepId)
                        .selectAll(CfgRuleTaskSteps.class)
                        .eq(CfgRuleTask::getRuleTaskId,ruleTaskId)
                        .eq(CfgRuleTaskSteps::getStatus,1)
                        .orderByAsc(CfgRuleTaskStepLink::getSeqnum)
        );
        if(cfgRuleTaskStepsList == null || cfgRuleTaskStepsList.size() == 0)
        {
            logXxlJobService.log(logXxlJob, EnumXxlLogOpType.TaskFinish.value, 0,0,2,null,"没有需要执行的策勒。请确认");
            return new CmdResVo(0,"没有找到需要执行的策略。");
        }
        executorService.executeRuleTask(usrId, ruleTaskId, logXxlJob,cfgRuleTaskStepsList);
        logXxlJob.setRuleStepId(null);
        logXxlJobService.log(logXxlJob, EnumXxlLogOpType.TaskStart.value, 0,0,1,null,"任务开始异步执行，请等待。");
        //update( new LambdaUpdateWrapper<CfgRuleTask>()
        //        .set(CfgRuleTask::getRunEndTime,new Date())
        //        .set(CfgRuleTask::getExecuteStatus, EnumRuleTaskRunStatus.OK.value)
        //        .eq(CfgRuleTask::getRuleTaskId,cfgRuleTask.getRuleTaskId())
        //);
        return new CmdResVo(0,"任务后台执行中，请等待。");
    }

    @Override
    public CmdResVo resetRuleTask(String usrId, Long ruleTaskId)
    {
        CfgRuleTask cfgRuleTask = getById(ruleTaskId);
        if( cfgRuleTask == null){

            return new CmdResVo(0,"该决策任务不存在");
        }
        cfgRuleTask.setMddt(new Date());
        cfgRuleTask.setMdusr(usrId);
        cfgRuleTask.setExecuteStatus(EnumRuleTaskRunStatus.Stop.value);
        updateById(cfgRuleTask);
        return  new CmdResVo(0,"更新成功");
    }
}




